#pragma once

#include "iostream"
#include "vector"
#include "algorithm"

using namespace std;
/*HJJ QQ479287006
 *给你一个整数数组 nums ，数组中的元素 互不相同 。返回该数组所有可能的子集（幂集）。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

 

示例 1：

输入：nums = [1,2,3]
输出：[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2：

输入：nums = [0]
输出：[[],[0]]

来源：力扣（LeetCode）
链接：https://leetcode.cn/problems/subsets
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * */

//TODO 这个算回溯求子集 问题 以前确实没Shaun过
//TODO 如果把 ⼦集问题、组合问题、分割问题都抽象为⼀棵树的话，
// 那么组合问题和分割问题都是收集树的叶⼦节点，⽽⼦集问题是找树的所有节点！    组合是收集一条树枝
// 所以每次不用过滤 直接 收集结果就行了

vector<vector<int>> ret;
vector<int> temp;

void subsetsBack(vector<int> &nums, int startIndex) {

    /**
     *
     * 在注释中，可以发现可以不写终止条件，因为本来我们就要遍历整颗树。
        有的同学可能担心不写终止条件会不会无限递归？
        并不会，因为每次递归的下一层就是从i+1开始的。
     *
     * */

    ret.push_back(temp);

    for (int i = startIndex; i < nums.size(); ++i) {
        temp.push_back(nums[i]);
        subsetsBack();
        temp.pop_back();
    }
}


vector<vector<int>> subsets(vector<int> &nums) {
    subsetsBack(nums, 0);
    return ret;
}